#include <head.h>
#include "share.h"

#define M 200

#define DATABASE "my.db"
#define select_init(readfds, sockfd, nfds) FD_ZERO(readfds);\
										   FD_SET(sockfd, readfds);\
										   nfds = sockfd

int msglen = sizeof(MSG);
pthread_mutex_t lock;

int do_register(ARG *arg)
{
	int ret;
	ret = insert_usrmsg(arg->db, arg->msg);
	printf("%d : %d : %s\n", arg->fd, __LINE__, __func__);
	if(ret == 0){
		strcpy(arg->msg.data, "register OK");
		ret = send(arg->fd, &arg->msg, msglen, 0);
		if(ret < 0){
			perror("fail to send\n");
		}
	}else{
		strcpy(arg->msg.data, "already exist");
		ret = send(arg->fd, &arg->msg, msglen, 0);
		if(ret < 0){
			err_log("fail to send\n");
		}
	}
	return 0;
}

int do_login(ARG *arg)
{
	int ret;
	ret = select_usrmsg(arg->db, arg->msg);
	printf("%d : %d : %s\n", arg->fd, __LINE__, __func__);
	if(ret == 1){
		strcpy(arg->msg.data, "login : OK");
		ret = send(arg->fd, &arg->msg, msglen, 0);
		if(ret < 0){
			perror("fail to send\n");
		}
	}else{
		strcpy(arg->msg.data, "login : name or password id wrony!");
		ret = send(arg->fd, &arg->msg, msglen, 0);
		if(ret < 0){
			err_log("fail to send\n");
		}
	}
	return 0;
}

int do_search(ARG *arg)
{
	int ret;
	if(arg->msg.user_type == 2){
	ret = select_usr(arg);
	}else if(arg->msg.user_type == 1){
		ret = select_usrall(arg);
	}
	if(ret == 0){
		return 0;
	}else{
		return -1;
	}
}

int do_query(ARG *arg)
{
	int ret;
	int found = do_search(arg);
	
	if(found == -1){
		strcpy(arg->msg.data, "not found");
		ret = send(arg->fd, &arg->msg, msglen, 0);
		if(ret < 0){
			err_log("fail to send\n");
		}
	}
	return 0;
}

int do_delete(ARG *arg){
	
	int ret;
	ret = delete_usr(arg->db, arg->msg);
	if(ret == 0){
		strcpy(arg->msg.data, "delete : OK");
		ret = send(arg->fd, &arg->msg, msglen, 0);
		if(ret < 0){
			err_log("fail to send\n");
		}
	}else{
		strcpy(arg->msg.data, "delete wrony!");
		ret = send(arg->fd, &arg->msg, msglen, 0);
		if(ret < 0){
			err_log("fail to send\n");
		}
	}
	return 0;
}

int do_modify(ARG *arg)
{	
	int ret;
	ret = update_usr(arg->db, arg->msg);
	if(ret == 0){
		strcpy(arg->msg.data, "update : OK");
		ret = send(arg->fd, &arg->msg, msglen, 0);
		if(ret < 0){
			err_log("fail to send\n");
		}
	}else{
		strcpy(arg->msg.data, "update wrony!");
		ret = send(arg->fd, &arg->msg, msglen, 0);
		if(ret < 0){
			err_log("fail to send\n");
		}
	}
	return 0;
}

void *start_routine(void *argc)
{
	int ret;
	pthread_mutex_lock(&lock);
	ARG arg = *(ARG*)argc;
	pthread_mutex_unlock(&lock);
	int fd = arg.fd;
	while(1){

		printf("%d : %d : %d: %s\n", arg.fd, arg.msg.user_type, __LINE__, __func__);
		//memset(&arg.msg, 0, msglen);
		ret = recv(fd, &arg.msg, msglen, 0);
		if(ret < 0){
			perror("fail to recv\n");
			break;
		}
		if(ret == 0){
			printf("%d quit\n", fd);
			close(fd);
			break;
		}

		arg.fd = fd;
		switch(arg.msg.action_type){
		case 'R':
			do_register(&arg);
			break;
		case 'L':
			do_login(&arg);
			break;
		case 'Q':
			do_query(&arg);
			break;
		case 'I':
			do_register(&arg);
			break;
		case 'D':
			do_delete(&arg);
			break;
		case 'M':
			do_modify(&arg);
			break;
		default:
			break;
		}
	}
}
int main(int argc, const char *argv[])
{
	int num = 0;
	int i;
	int nfds;
	int temp;
	fd_set tempfds, readfds;
	int ret;//接受返回值
	MSG msg;//信息结构体
	int sockfd;
	ARG arg;//给线程函数的信息
	sqlite3 *db;
	int clientfd;
	pthread_t thread[M];
	struct sockaddr_in serveraddr, clientaddr;

	socklen_t addrlen = sizeof(struct sockaddr);

	if(argc != 3){
		printf("Usage: %s ip port\n", argv[0]);
		return -1;
	}

	db = open_db(DATABASE);
	ret = create_usr_table(db);
	arg.db = db;

	sockfd = TCP_server_sockfd_init(argv[1], argv[2], &serveraddr);
	pthread_mutex_init(&lock, NULL);

	//select_init(&readfds, sockfd, nfds);

	while(1){
	/*	tempfds = readfds;
		ret = select(nfds+1, &tempfds, NULL, NULL, NULL);
		if(ret < 0){
			perror("fail to select\n");
		}
		if(ret > 0){
			for(i = 3; i < nfds+1; i++){
				if(FD_ISSET(i, &tempfds)){
					if(i == sockfd){
						clientfd  = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen);
						if(clientfd < 0){
							err_log("fail to accept\n");
						}
						arg.fd = clientfd;
						printf("%d: %s -> %d\n", clientfd, inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));

						FD_SET(clientfd, &readfds);
						nfds = clientfd > nfds ? clientfd:nfds;
					}else if(i >= 3){
						//temp = i;
						arg.msg = msg;						
						if(num < M){
						ret = pthread_create(&thread[num], NULL, start_routine, &arg);
						if(ret < 0){
							err_log("fail to pthread_create\n");
						}
						printf("thread: %u\n", (int)thread[num]);
						FD_CLR(i, &readfds);
						ret = pthread_detach(thread[num]);//把线程标记为分离
						num++;
						}
					}
				}
				}}*/

		clientfd  = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen);
		if(clientfd < 0){
			err_log("fail to accept\n");
		}
		arg.fd = clientfd;
		printf("%d: %s -> %d\n", clientfd, inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));

		if(num < M){
			ret = pthread_create(&thread[num], NULL, start_routine, &arg);
			if(ret < 0){
				err_log("fail to pthread_create\n");
			}
			printf("thread: %u\n", (int)thread[num]);
			ret = pthread_detach(thread[num]);//把线程标记为分离
			num++;
		}
		else{
			printf("reach the MAX\n");
		}
	}
				return 0;
}
